package org.example.my_netty.worker;


import lombok.Setter;
import org.example.my_netty.MyNettyContext;

import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

//工作者  内含一个selector和一个执行器（线程的简化 不然要类线程池整合到group里 懒得搞了）
public class MyWorker {


    //了防止多层依赖 让他从持有一个context 存公共的信息
    @Setter
    public MyNettyContext context;

    private Selector selector;


    //执行单元 这里直接是线程池算了
    private final ExecutorService executorService= Executors.newFixedThreadPool(1);


    public MyWorker() {
    }

    // 启动任务 现在暂时只有一个任务  所以直接注册然后给
    public void start(SelectionKey key) {

        try {
            //懒加载
            if (selector == null) {
                selector = Selector.open();
            }

            //根据这个key拿到对应的大channel 再拿到小channel 注册到selector
            ServerSocketChannel serverSocketChannel = (ServerSocketChannel) key.channel();
            SocketChannel socketChannel = serverSocketChannel.accept();
            socketChannel.configureBlocking(false);
            //新的selector监听 所有事件都要注册 管他呢 反正触发之后不响应也是响应
            socketChannel.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);


            //启动后丢进执行器
            executorService.execute(() -> {
                try {
                    workerWork();
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            });

        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    //实际的主流程 目前就是响应读事件 执行读链
    private void workerWork() throws Exception {
        //主流程
        while (true) {
            //监听 阻塞等待时间触发
            selector.select();
            //此时有事件触发了
            Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
            while (iterator.hasNext()) {
                //拿到事件并移除
                SelectionKey key = iterator.next();
                iterator.remove();
                //目前只有读事件
                if (key.isReadable()) {
                    context.handle((SocketChannel) key.channel());
                }

            }
        }
    }


}
